/*
 * Copyright 2002-2021 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.context.support;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.beans.BeansException;
import org.springframework.beans.CachedIntrospectionResults;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.support.ResourceEditorRegistrar;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.HierarchicalMessageSource;
import org.springframework.context.LifecycleProcessor;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.MessageSourceResolvable;
import org.springframework.context.NoSuchMessageException;
import org.springframework.context.PayloadApplicationEvent;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.event.ApplicationEventMulticaster;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.ContextStartedEvent;
import org.springframework.context.event.ContextStoppedEvent;
import org.springframework.context.event.SimpleApplicationEventMulticaster;
import org.springframework.context.expression.StandardBeanExpressionResolver;
import org.springframework.context.weaving.LoadTimeWeaverAware;
import org.springframework.context.weaving.LoadTimeWeaverAwareProcessor;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils;

/**
 * Abstract implementation of the {@link org.springframework.context.ApplicationContext}
 * interface. Doesn't mandate the type of storage used for configuration; simply
 * implements common context functionality. Uses the Template Method design pattern,
 * requiring concrete subclasses to implement abstract methods.
 *
 * <p>In contrast to a plain BeanFactory, an ApplicationContext is supposed
 * to detect special beans defined in its internal bean factory:
 * Therefore, this class automatically registers
 * {@link org.springframework.beans.factory.config.BeanFactoryPostProcessor BeanFactoryPostProcessors},
 * {@link org.springframework.beans.factory.config.BeanPostProcessor BeanPostProcessors},
 * and {@link org.springframework.context.ApplicationListener ApplicationListeners}
 * which are defined as beans in the context.
 *
 * <p>A {@link org.springframework.context.MessageSource} may also be supplied
 * as a bean in the context, with the name "messageSource"; otherwise, message
 * resolution is delegated to the parent context. Furthermore, a multicaster
 * for application events can be supplied as an "applicationEventMulticaster" bean
 * of type {@link org.springframework.context.event.ApplicationEventMulticaster}
 * in the context; otherwise, a default multicaster of type
 * {@link org.springframework.context.event.SimpleApplicationEventMulticaster} will be used.
 *
 * <p>Implements resource loading by extending
 * {@link org.springframework.core.io.DefaultResourceLoader}.
 * Consequently treats non-URL resource paths as class path resources
 * (supporting full class path resource names that include the package path,
 * e.g. "mypackage/myresource.dat"), unless the {@link #getResourceByPath}
 * method is overridden in a subclass.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @author Mark Fisher
 * @author Stephane Nicoll
 * @author Sam Brannen
 * @since January 21, 2001
 * @see #refreshBeanFactory
 * @see #getBeanFactory
 * @see org.springframework.beans.factory.config.BeanFactoryPostProcessor
 * @see org.springframework.beans.factory.config.BeanPostProcessor
 * @see org.springframework.context.event.ApplicationEventMulticaster
 * @see org.springframework.context.ApplicationListener
 * @see org.springframework.context.MessageSource
 */
public abstract class AbstractApplicationContext extends DefaultResourceLoader
		implements ConfigurableApplicationContext {

	/**
	 * Name of the MessageSource bean in the factory.
	 * If none is supplied, message resolution is delegated to the parent.
	 * @see MessageSource
	 */
	public static final String MESSAGE_SOURCE_BEAN_NAME = "messageSource";

	/**
	 * Name of the LifecycleProcessor bean in the factory.
	 * If none is supplied, a DefaultLifecycleProcessor is used.
	 * @see org.springframework.context.LifecycleProcessor
	 * @see org.springframework.context.support.DefaultLifecycleProcessor
	 */
	public static final String LIFECYCLE_PROCESSOR_BEAN_NAME = "lifecycleProcessor";

	/**
	 * Name of the ApplicationEventMulticaster bean in the factory.
	 * If none is supplied, a default SimpleApplicationEventMulticaster is used.
	 * @see org.springframework.context.event.ApplicationEventMulticaster
	 * @see org.springframework.context.event.SimpleApplicationEventMulticaster
	 */
	public static final String APPLICATION_EVENT_MULTICASTER_BEAN_NAME = "applicationEventMulticaster";


	static {
		// 优先加载上下文关闭事件来防止奇怪的类加载问题在应用程序关闭的时候
		// Eagerly load the ContextClosedEvent class to avoid weird classloader issues
		// on application shutdown in WebLogic 8.1. (Reported by Dustin Woods.)
		ContextClosedEvent.class.getName();
	}


	/**
	 * 用于记录日志，供该类及其子类使用
	 *
	 * Logger used by this class. Available to subclasses. */
	protected final Log logger = LogFactory.getLog(getClass());

	/**
	 * 当前应用上下文的唯一标识，用于区分不同上下文实例
	 *
	 * Unique id for this context, if any. */
	private String id = ObjectUtils.identityToString(this);

	/**
	 * 应用上下文的显示名称，方便识别和调试
	 *
	 * Display name. */
	private String displayName = ObjectUtils.identityToString(this);

	/**
	 * 当前上下文的父上下文，支持上下文的层级结构和资源共享
	 *
	 * Parent context. */
	@Nullable
	private ApplicationContext parent;

	/**
	 * 当前上下文所使用的环境变量和配置变量的集合，封装配置信息
	 *
	 * Environment used by this context. */
	@Nullable
	private ConfigurableEnvironment environment;

	/**
	 * 在容器刷新时需要执行的BeanFactory后置处理器列表，用于定制或修改Bean定义
	 *
	 * BeanFactoryPostProcessors to apply on refresh. */
	private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors = new ArrayList<>();

	/**
	 * 当前上下文启动的系统时间戳，用于性能监控或日志
	 *
	 * System time in milliseconds when this context started. */
	private long startupDate;

	/**
	 * 标记当前上下文是否处于激活状态，保证线程安全的状态管理
	 *
	 * Flag that indicates whether this context is currently active. */
	private final AtomicBoolean active = new AtomicBoolean();

	/**
	 * 标记当前上下文是否已经关闭，避免重复关闭操作
	 *
	 * Flag that indicates whether this context has been closed already. */
	private final AtomicBoolean closed = new AtomicBoolean();

	/**
	 * 用于刷新和销毁操作的同步锁，保证线程安全
	 *
	 * Synchronization monitor for the "refresh" and "destroy". */
	private final Object startupShutdownMonitor = new Object();

	/**
	 * JVM关闭时注册的钩子线程引用，用于优雅关闭上下文
	 *
	 * Reference to the JVM shutdown hook, if registered. */
	@Nullable
	private Thread shutdownHook;

	/**
	 * 资源路径模式解析器，用于加载匹配路径的资源文件
	 *
	 * ResourcePatternResolver used by this context. */
	private ResourcePatternResolver resourcePatternResolver;

	/**
	 * 负责管理上下文内bean的生命周期，如启动、停止等操作
	 *
	 * LifecycleProcessor for managing the lifecycle of beans within this context. */
	@Nullable
	private LifecycleProcessor lifecycleProcessor;

	/**
	 * 国际化资源信息的代理对象，处理消息资源的查找和解析
	 *
	 * MessageSource we delegate our implementation of this interface to. */
	@Nullable
	private MessageSource messageSource;

	/**
	 * 事件多播器，负责事件的发布和监听器的管理
	 *
	 * Helper class used in event publishing. */
	@Nullable
	private ApplicationEventMulticaster applicationEventMulticaster;

	/**
	 * 静态注册的应用监听器集合，在上下文启动时注册，正式使用的应用程序监听器集合
	 * 这是当前Spring上下文正在使用的所有事件监听器集合。当容器启动或刷新完成后，事件通知都是通过这个集合发送的。
	 *
	 * Statically specified listeners. */
	private final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();

	/**
	 * Local listeners registered before refresh.
	 * 刷新前的监听器快照（备份），用于多次刷新时恢复初始状态。
	 *
	 * 这个集合是 applicationListeners 的快照，首次刷新时会将当前的
	 * applicationListeners 复制一份存入该集合，方便二次刷新时将监听器集合
	 * 重置为刷新前的状态，保证监听器不会重复添加或遗漏。
	 *
	 * 注意：此集合不会主动添加监听器，只做备份和恢复用。
	 */
	@Nullable
	private Set<ApplicationListener<?>> earlyApplicationListeners;

	/**
	 * ApplicationEvents published before the multicaster setup.
	 * 容器初始化完成前发布的事件缓存。
	 * 用于缓存刷新过程中产生的事件，确保容器初始化后能正确发布这些事件。
	 */
	@Nullable
	private Set<ApplicationEvent> earlyApplicationEvents;


	/**
	 * 创建一个无父类的AbstractApplication对象
	 *
	 * Create a new AbstractApplicationContext with no parent.
	 */
	public AbstractApplicationContext() {
		// 创建资源模式处理器
		// 用来解决当前容器启动所需要资源，比如：配置文件
		this.resourcePatternResolver = getResourcePatternResolver();
	}

	/**
	 * Create a new AbstractApplicationContext with the given parent context.
	 * 使用给定的父上下文创建一个新的 AbstractApplicationContext 实例。
	 *
	 * @param parent the parent context
	 *               父上下文对象
	 */
	public AbstractApplicationContext(@Nullable ApplicationContext parent) {
		// 调用无参构造方法，进行默认初始化
		this();
		// 设置父上下文
		setParent(parent);
	}


	//---------------------------------------------------------------------
	// Implementation of ApplicationContext interface
	//---------------------------------------------------------------------

	/**
	 * Set the unique id of this application context.
	 * <p>Default is the object id of the context instance, or the name
	 * of the context bean if the context is itself defined as a bean.
	 * @param id the unique id of the context
	 */
	@Override
	public void setId(String id) {
		this.id = id;
	}

	@Override
	public String getId() {
		return this.id;
	}

	@Override
	public String getApplicationName() {
		return "";
	}

	/**
	 * Set a friendly name for this context.
	 * Typically done during initialization of concrete context implementations.
	 * <p>Default is the object id of the context instance.
	 */
	public void setDisplayName(String displayName) {
		Assert.hasLength(displayName, "Display name must not be empty");
		this.displayName = displayName;
	}

	/**
	 * Return a friendly name for this context.
	 * @return a display name for this context (never {@code null})
	 */
	@Override
	public String getDisplayName() {
		return this.displayName;
	}

	/**
	 * Return the parent context, or {@code null} if there is no parent
	 * (that is, this context is the root of the context hierarchy).
	 */
	@Override
	@Nullable
	public ApplicationContext getParent() {
		return this.parent;
	}

	/**
	 * Set the {@code Environment} for this application context.
	 * <p>Default value is determined by {@link #createEnvironment()}. Replacing the
	 * default with this method is one option but configuration through {@link
	 * #getEnvironment()} should also be considered. In either case, such modifications
	 * should be performed <em>before</em> {@link #refresh()}.
	 * @see org.springframework.context.support.AbstractApplicationContext#createEnvironment
	 */
	@Override
	public void setEnvironment(ConfigurableEnvironment environment) {
		this.environment = environment;
	}

	/**
	 * Return the {@code Environment} for this application context in configurable
	 * form, allowing for further customization.
	 * <p>If none specified, a default environment will be initialized via
	 * {@link #createEnvironment()}.
	 */
	@Override
	public ConfigurableEnvironment getEnvironment() {
		if (this.environment == null) {
			this.environment = createEnvironment();
		}
		return this.environment;
	}

	/**
	 * Create and return a new {@link StandardEnvironment}.
	 * <p>Subclasses may override this method in order to supply
	 * a custom {@link ConfigurableEnvironment} implementation.
	 */
	protected ConfigurableEnvironment createEnvironment() {
		return new StandardEnvironment();
	}

	/**
	 * Return this context's internal bean factory as AutowireCapableBeanFactory,
	 * if already available.
	 * @see #getBeanFactory()
	 */
	@Override
	public AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException {
		return getBeanFactory();
	}

	/**
	 * Return the timestamp (ms) when this context was first loaded.
	 */
	@Override
	public long getStartupDate() {
		return this.startupDate;
	}

	/**
	 * 将给定事件发布到所有监听器
	 *
	 * Publish the given event to all listeners.
	 * <p>Note: Listeners get initialized after the MessageSource, to be able
	 * to access it within listener implementations. Thus, MessageSource
	 * implementations cannot publish events.
	 * @param event the event to publish (may be application-specific or a
	 * standard framework event)
	 */
	@Override
	public void publishEvent(ApplicationEvent event) {
		publishEvent(event, null);
	}

	/**
	 * 将给定事件发布到所有监听器
	 *
	 * Publish the given event to all listeners.
	 * <p>Note: Listeners get initialized after the MessageSource, to be able
	 * to access it within listener implementations. Thus, MessageSource
	 * implementations cannot publish events.
	 * @param event the event to publish (may be an {@link ApplicationEvent}
	 * or a payload object to be turned into a {@link PayloadApplicationEvent})
	 */
	@Override
	public void publishEvent(Object event) {
		publishEvent(event, null);
	}

	/**
	 * 将给定事件发布到所有监听器
	 *
	 * Publish the given event to all listeners.
	 * @param event the event to publish (may be an {@link ApplicationEvent}
	 * or a payload object to be turned into a {@link PayloadApplicationEvent})
	 * @param eventType the resolved event type, if known
	 * @since 4.2
	 */
	protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
		// 如果event为null，抛出异常
		Assert.notNull(event, "Event must not be null");

		// Decorate event as an ApplicationEvent if necessary
		// 装饰事件作为一个应用事件，如果有必要
		ApplicationEvent applicationEvent;
		// 如果event是ApplicationEvent的实例
		if (event instanceof ApplicationEvent) {
			// 将event强转为ApplicationEvent对象
			applicationEvent = (ApplicationEvent) event;
		}
		else {
			// PayloadApplicationEvent：携带任意有效负载的ApplicationEvent。
			// 创建一个新的PayloadApplicationEvent
			applicationEvent = new PayloadApplicationEvent<>(this, event);
			// 如果eventType为 null
			if (eventType == null) {
				// 将applicationEvent转换为PayloadApplicationEvent 象，引用其ResolvableType对象
				eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
			}
		}

		// Multicast right now if possible - or lazily once the multicaster is initialized
		// 如果可能的话，现在就进行组播——或者在组播初始化后延迟
		// earlyApplicationEvents：在多播程序设置之前发布的ApplicationEvent
		// 如果earlyApplicationEvents不为 null，这种情况只在上下文的多播器还没有初始化的情况下才会成立，会将applicationEvent
		// 添加到earlyApplicationEvents保存起来，待多博器初始化后才继续进行多播到适当的监听器
		if (this.earlyApplicationEvents != null) {
			//将applicationEvent添加到 earlyApplicationEvents
			this.earlyApplicationEvents.add(applicationEvent);
		}
		else {
			// 多播applicationEvent到适当的监听器
			getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
		}

		// Publish event via parent context as well...
		// 通过父上下文发布事件
		// 如果parent不为null
		if (this.parent != null) {
			// 如果parent是AbstractApplicationContext的实例
			if (this.parent instanceof AbstractApplicationContext) {
				// 将event多播到所有适合的监听器。如果event不是ApplicationEvent实例，会将其封装成PayloadApplicationEvent对象再进行多播
				((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
			}
			else {
				// 通知与event事件应用程序注册的所有匹配的监听器
				this.parent.publishEvent(event);
			}
		}
	}

	/**
	 * Return the internal ApplicationEventMulticaster used by the context.
	 * @return the internal ApplicationEventMulticaster (never {@code null})
	 * @throws IllegalStateException if the context has not been initialized yet
	 */
	ApplicationEventMulticaster getApplicationEventMulticaster() throws IllegalStateException {
		if (this.applicationEventMulticaster == null) {
			throw new IllegalStateException("ApplicationEventMulticaster not initialized - " +
					"call 'refresh' before multicasting events via the context: " + this);
		}
		return this.applicationEventMulticaster;
	}

	/**
	 * Return the internal LifecycleProcessor used by the context.
	 * @return the internal LifecycleProcessor (never {@code null})
	 * @throws IllegalStateException if the context has not been initialized yet
	 */
	LifecycleProcessor getLifecycleProcessor() throws IllegalStateException {
		if (this.lifecycleProcessor == null) {
			throw new IllegalStateException("LifecycleProcessor not initialized - " +
					"call 'refresh' before invoking lifecycle methods via the context: " + this);
		}
		return this.lifecycleProcessor;
	}

	/**
	 * Return the ResourcePatternResolver to use for resolving location patterns
	 * into Resource instances. Default is a
	 * {@link org.springframework.core.io.support.PathMatchingResourcePatternResolver},
	 * supporting Ant-style location patterns.
	 * <p>Can be overridden in subclasses, for extended resolution strategies,
	 * for example in a web environment.
	 * <p><b>Do not call this when needing to resolve a location pattern.</b>
	 * Call the context's {@code getResources} method instead, which
	 * will delegate to the ResourcePatternResolver.
	 * @return the ResourcePatternResolver for this context
	 * @see #getResources
	 * @see org.springframework.core.io.support.PathMatchingResourcePatternResolver
	 */
	protected ResourcePatternResolver getResourcePatternResolver() {
		// 创建一个资源模式解析器（其实就是用来解析xml配置文件的）
		return new PathMatchingResourcePatternResolver(this);
	}


	//---------------------------------------------------------------------
	// Implementation of ConfigurableApplicationContext interface
	//---------------------------------------------------------------------

	/**
	 * Set the parent of this application context.
	 * 设置当前应用上下文的父上下文。
	 *
	 * <p>The parent {@linkplain ApplicationContext#getEnvironment() environment} is
	 * 父上下文的 {@linkplain ApplicationContext#getEnvironment() 环境} 会
	 *
	 * {@linkplain ConfigurableEnvironment#merge(ConfigurableEnvironment) merged} with
	 * 通过 {@linkplain ConfigurableEnvironment#merge(ConfigurableEnvironment) 合并} 到
	 *
	 * this (child) application context environment if the parent is non-{@code null} and
	 * 当前（子）应用上下文的环境中（如果父上下文不为 {@code null} 且
	 *
	 * its environment is an instance of {@link ConfigurableEnvironment}.
	 * 它的环境是 {@link ConfigurableEnvironment} 类型的实例）。
	 *
	 * @see ConfigurableEnvironment#merge(ConfigurableEnvironment)
	 * 参见 ConfigurableEnvironment#merge(ConfigurableEnvironment)
	 */
	@Override
	public void setParent(@Nullable ApplicationContext parent) {
		// 将传入的 ApplicationContext 对象设置为当前上下文的父上下文
		this.parent = parent;

		// 如果父上下文不为空
		if (parent != null) {
			// 获取父上下文的环境对象
			Environment parentEnvironment = parent.getEnvironment();

			// 如果父环境是 ConfigurableEnvironment 类型
			if (parentEnvironment instanceof ConfigurableEnvironment) {
				// 将父环境合并到当前（子）上下文的环境中
				getEnvironment().merge((ConfigurableEnvironment) parentEnvironment);
			}
		}
	}

	@Override
	public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor) {
		Assert.notNull(postProcessor, "BeanFactoryPostProcessor must not be null");
		this.beanFactoryPostProcessors.add(postProcessor);
	}

	/**
	 * Return the list of BeanFactoryPostProcessors that will get applied
	 * to the internal BeanFactory.
	 */
	public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {
		return this.beanFactoryPostProcessors;
	}

	@Override
	public void addApplicationListener(ApplicationListener<?> listener) {
		Assert.notNull(listener, "ApplicationListener must not be null");
		if (this.applicationEventMulticaster != null) {
			this.applicationEventMulticaster.addApplicationListener(listener);
		}
		this.applicationListeners.add(listener);
	}

	/**
	 * Return the list of statically specified ApplicationListeners.
	 */
	public Collection<ApplicationListener<?>> getApplicationListeners() {
		return this.applicationListeners;
	}

	/**
	 * Core Function / 核心功能:
	 * - This method is the central entry point for refreshing the Spring ApplicationContext.
	 * - It destroys and recreates the internal BeanFactory, reinitializes beans, infrastructure,
	 *   event system, message source, and ensures the context is fully ready for use.
	 *
	 * - 本方法是 Spring ApplicationContext 刷新的核心入口。
	 * - 它会销毁并重建内部 BeanFactory，重新初始化 Bean、基础设施组件、事件系统、国际化消息源，
	 *   确保容器刷新后处于“全新可用”的状态。
	 */
	@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			// 准备刷新该上下文，进行初始化准备工作
			// 主要操作包括：
			// 1、设置当前时间为容器启动时间（startupDate），用于后续监控和日志记录
			// 2、将容器活跃状态（active）设置为true，表示容器正在运行中
			// 3、将容器关闭状态（closed）设置为false，表示容器未关闭
			// 4、初始化环境（Environment）对象，加载系统环境变量、配置属性等
			// 5、初始化监听器和事件的相关集合（listeners、earlyApplicationEvents）
			//    以便后续事件发布和监听器注册使用
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			// 告诉子类刷新内部的 BeanFactory，获取一个新的 BeanFactory 实例
			// 具体操作：
			// - 创建 DefaultListableBeanFactory 实例（或者子类覆盖的其他工厂）
			// - 设置序列化ID，便于序列化与反序列化操作
			// - 根据配置加载 BeanDefinition（例如从 XML 或注解扫描）
			// - 返回刷新后的 BeanFactory
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			// 准备 BeanFactory，对各种属性进行填充
			// 具体步骤包括：
			// - 设置 ClassLoader、ExpressionResolver 等核心组件
			// - 注册各种默认的 PropertyEditor、BeanPostProcessor 等
			// - 注册自动装配的后置处理器（例如处理@Autowired 注解）
			// - 允许子类进行进一步自定义
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				// 允许子类对 BeanFactory 进行后置处理
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				// 调用 BeanFactoryPostProcessor（对 BeanDefinition 进行修改）
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
				// 注册 BeanPostProcessor，用于拦截和增强 Bean 的生命周期
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
				// 初始化国际化消息源 MessageSource
				// 为上下文初始化message源，即不同语言的消息体，国际化处理，在springMVC的时候通过国际化的代码重点讲解
				initMessageSource();

				// Initialize event multicaster for this context.
				// 初始化事件多播器，用于事件发布
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				// 由子类初始化其他特殊 Bean
				onRefresh();

				// Check for listener beans and register them.
				// 检查并注册事件监听器
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				// 实例化所有非延迟加载的单例 Bean
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				// 最后一步：发布上下文刷新完成事件
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				// 销毁已经创建的单例 Bean，防止资源泄露
				destroyBeans();

				// Reset 'active' flag.
				// 重置上下文活动标志，取消刷新
				cancelRefresh(ex);

				// Propagate exception to caller.
				// 将异常抛给调用方
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				// 重置 Spring 核心中通用的内省缓存，避免内存泄漏
				resetCommonCaches();
			}
		}
	}

	/**
	 * Prepare this context for refreshing, setting its startup date and
	 * active flag as well as performing any initialization of property sources.
	 *
	 * 准备刷新上下文，设置启动日期和激活标志，
	 * 同时执行属性源的任何初始化操作。
	 */
	protected void prepareRefresh() {
		// Switch to active.
		// 设置容器启动的启动时间
		this.startupDate = System.currentTimeMillis();
		// 容器关闭标志位
		this.closed.set(false);
		// 容器的激活标志位
		this.active.set(true);

		// 记录日志
		if (logger.isDebugEnabled()) {
			if (logger.isTraceEnabled()) {
				logger.trace("Refreshing " + this);
			}
			else {
				logger.debug("Refreshing " + getDisplayName());
			}
		}

		// Initialize any placeholder property sources in the context environment.
		// 初始化上下文环境中的所有占位符属性源
		// 留给子类覆盖
		initPropertySources();

		// Validate that all properties marked as required are resolvable:
		// see ConfigurablePropertyResolver#setRequiredProperties
		// 验证所有标记为必需的属性是否可解析：
		// 参见 ConfigurablePropertyResolver#setRequiredProperties
		// 创建并获取环境对象，验证需要的属性文件是否都已经放入环境中
		getEnvironment().validateRequiredProperties();

		// Store pre-refresh ApplicationListeners...
		// 存储刷新前的ApplicationListeners...
		/**
		 * 存储刷新前的ApplicationListeners，目的是支持Spring容器的多次刷新操作。
		 *
		 * Spring容器在以下场景可能会多次刷新：
		 * 1. Spring Cloud Config动态刷新配置时，需要重新加载上下文并通知监听器。
		 * 2. 动态模块加载或插件机制中，部分上下文可能被重新刷新。
		 * 3. Web应用热部署或服务器重启时，容器上下文会刷新。
		 * 4. 开发工具（如Spring DevTools）触发的容器刷新。
		 * 5. 测试环境中使用@DirtiesContext等机制导致的上下文重置。
		 *
		 * 因此，earlyApplicationListeners用于缓存刷新前的监听器，避免多次刷新时监听器重复注册或丢失，
		 * 保持监听器状态的一致性和正确性。
		 */
		if (this.earlyApplicationListeners == null) {
			this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
		}
		else {
			// Reset local application listeners to pre-refresh state.
			// 将本地应用程序监听器重置为刷新前状态
			this.applicationListeners.clear();
			this.applicationListeners.addAll(this.earlyApplicationListeners);
		}

		// Allow for the collection of early ApplicationEvents,
		// to be published once the multicaster is available...
		// 允许收集早期的ApplicationEvents，
		// 以便在多播器可用时发布...
		// 创建刷新前的监听事件集合
		this.earlyApplicationEvents = new LinkedHashSet<>();
	}

	/**
	 * <p>Replace any stub property sources with actual instances.
	 * @see org.springframework.core.env.PropertySource.StubPropertySource
	 * @see org.springframework.web.context.support.WebApplicationContextUtils#initServletPropertySources
	 */
	protected void initPropertySources() {
		// For subclasses: do nothing by default.
	}

	/**
	 * 获取一个全新的BeanFactory示例
	 *
	 * Core Function / 核心功能:
	 * This method ensures that the ApplicationContext holds a fresh, fully initialized
	 * BeanFactory by instructing subclasses to refresh it and then returning the new instance.
	 *
	 * 本方法的核心作用是：确保当前 ApplicationContext 持有一个**全新且已经初始化**的 BeanFactory。
	 * 它通过调用子类实现的刷新逻辑 `refreshBeanFactory()` 来销毁旧的 BeanFactory 并创建新的，
	 * 然后再通过 `getBeanFactory()` 返回该实例。
	 *
	 * ----------------------------------------------------------------------------------------
	 * Logic Flow / 逻辑流程:
	 * 1. 调用 `refreshBeanFactory()` —— 抽象方法，由具体子类（如 `AbstractRefreshableApplicationContext`）实现。
	 *    - 销毁旧的 BeanFactory（如果已存在），并释放相关资源。
	 *    - 创建新的 BeanFactory 实例。
	 *    - 加载 Bean 定义（例如 XML/注解/Java 配置等），注册到 BeanFactory 中。
	 *
	 * 2. 调用 `getBeanFactory()` —— 获取刚刚初始化完成的 BeanFactory 实例。
	 *
	 * 3. 返回该 BeanFactory —— 供后续整个容器生命周期使用。
	 *
	 * ----------------------------------------------------------------------------------------
	 * Role in Spring Framework / 在 Spring 框架中的作用:
	 * - 本方法是 Spring 容器 **refresh 流程** 的核心步骤之一。
	 * - 它位于 `AbstractApplicationContext#refresh()` 调用链中：
	 *      refresh() → obtainFreshBeanFactory() → refreshBeanFactory() & getBeanFactory()
	 * - 前置调用：`refresh()` 负责整体上下文重建，会先清理旧的上下文，再调用本方法。
	 * - 后续调用：返回的 `BeanFactory` 将被用于：
	 *      - BeanDefinition 的后置处理（invokeBeanFactoryPostProcessors）
	 *      - BeanPostProcessor 注册
	 *      - 单例 Bean 的实例化与依赖注入
	 *
	 * 也就是说，obtainFreshBeanFactory 是 Spring IoC 容器在刷新时 **承上启下的关键桥梁**。
	 *
	 * ----------------------------------------------------------------------------------------
	 * Design Pattern & Architecture / 设计模式与架构思想:
	 * 1. **Template Method 模板方法模式**
	 *    - 本方法由抽象父类定义固定调用流程（先刷新，再获取 BeanFactory），
	 *      具体实现由子类完成（refreshBeanFactory 的实现差异化）。
	 *    - 优点：抽象出稳定的刷新流程，方便扩展（XML/注解/混合配置容器）。
	 *    - 缺点：继承层次较深，调试和维护成本高。
	 *
	 * 2. **IoC 容器分层架构思想**
	 *    - ApplicationContext（更高层，带有上下文特性）
	 *    - BeanFactory（底层 IoC 核心）
	 *    obtainFreshBeanFactory 就是二者衔接的桥梁，体现了 Spring 容器的分层解耦。
	 *
	 * ----------------------------------------------------------------------------------------
	 * @return the fresh BeanFactory instance
	 *         返回刷新后全新的 BeanFactory 实例
	 * @see #refreshBeanFactory()
	 * @see #getBeanFactory()
	 */
	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		// Call to refresh the BeanFactory: destroys old one (if any) and creates a new one.
		// 调用刷新 BeanFactory 的方法：销毁旧的（若存在），创建新的。
		// 子类会在这里读取 Bean 定义（XML/注解等），并注册到新的 BeanFactory 中。
		refreshBeanFactory();

		// Return the current BeanFactory held by this context
		// 返回当前上下文持有的 BeanFactory（即刚刚刷新后的实例）
		return getBeanFactory();
	}

	/**
	 * Configure the factory's standard context characteristics,
	 * such as the context's ClassLoader and post-processors.
	 * 配置工厂的标准上下文特性，
	 * 例如上下文的类加载器和后置处理器等。
	 *
	 * @param beanFactory the BeanFactory to configure 需要配置的 BeanFactory
	 */
	protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		// Tell the internal bean factory to use the context's class loader etc.
		// 设置 BeanFactory 的 classloader 为当前的上下文的类加载器
		beanFactory.setBeanClassLoader(getClassLoader());
		// 设置表达式解析器，支持 Spring 表达式语言（SpEL）
		beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
		// 注册资源编辑器，支持将资源路径等字符串注入为 Resource 类型
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		// Configure the bean factory with context callbacks.
		// 注册处理 Spring 上下文感知接口的后置处理器（ApplicationContextAwareProcessor），该类用来完成某些Aware对象的注入，比如：ApplicationContextAware
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
		// 忽略特定 Aware 接口的自动装配，这些接口（如 ApplicationContextAware）不是普通 Bean 依赖，
		// 而是由专门的 Bean 后置处理器（如 ApplicationContextAwareProcessor）在初始化阶段通过 setter 注入，
		// 避免普通 autowire 干扰。例如，MyBean 实现 ApplicationContextAware 后，容器会自动调用 setApplicationContext 方法注入 ApplicationContext，而不是通过 @Autowired 注入。
		beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
		beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
		beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
		beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

		// BeanFactory interface not registered as resolvable type in a plain factory.
		// 设置几个自动装配的特殊规则，当进行ioc初始化时，如果有多个实现，那么就使用指定的对象进行注入
		// 注册一些常用接口，使其在自动装配时能够解析到对应实例：
		// 将 BeanFactory 自身注册为可解析依赖
		beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
		// 将 ResourceLoader（当前 ApplicationContext）注册为可解析依赖
		beanFactory.registerResolvableDependency(ResourceLoader.class, this);
		// 将 ApplicationEventPublisher（当前 ApplicationContext）注册为可解析依赖
		beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
		// 将 ApplicationContext（当前实例）注册为可解析依赖
		beanFactory.registerResolvableDependency(ApplicationContext.class, this);

		// Register early post-processor for detecting inner beans as ApplicationListeners.
		// 注册一个早期的 BeanPostProcessor，用于检测内部声明的 Bean 是否实现了 ApplicationListener 接口，
		// 以便后续自动注册监听器
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

		// Detect a LoadTimeWeaver and prepare for weaving, if found.
		// 增加对 AspectJ 的支持
		// 在 Java 中，切面的织入（Weaving）有三种方式：
		// 1. 编译期织入（Compile-time Weaving）：
		//    使用特殊的 AspectJ 编译器（ajc）在 Java 编译阶段，将切面逻辑织入到目标类字节码中。
		// 2. 类加载期织入（Load-time Weaving, LTW）：
		//    通过特殊类加载器在类加载到 JVM 时，将切面织入字节码。
		// 3. 运行期织入（Runtime Weaving）：
		//    通过代理机制（如 JDK 动态代理或 CGLIB）在运行时创建目标类的代理对象，实现切面逻辑。
		//
		// AspectJ 提供两种主要织入方式：
		// - 编译期织入（Compile-time Weaving）
		// - 类加载期织入（Load-time Weaving）
		//
		// 下面的代码判断容器中是否存在 LTW 的 Bean，如果存在，则支持类加载期织入：
		if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			// 注册与 LoadTimeWeaver 相关的后置处理器
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			// Set a temporary ClassLoader for type matching.
			// 设置临时类加载器，用于类型匹配
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}

		// Register default environment beans.
		// 注册默认的系统环境（Environment、SystemProperties 和 SystemEnvironment）bean到一级缓存中
		if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
		}
	}

	/**
	 * Modify the application context's internal bean factory after its standard
	 * initialization. All bean definitions will have been loaded, but no beans
	 * will have been instantiated yet. This allows for registering special
	 * BeanPostProcessors etc in certain ApplicationContext implementations.
	 * @param beanFactory the bean factory used by the application context
	 */
	protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	}

	/**
	 * Instantiate and invoke all registered BeanFactoryPostProcessor beans,
	 * respecting explicit order if given.
	 * <p>Must be called before singleton instantiation.
	 *
	 * 实例化并调用所有已注册的 BeanFactoryPostProcessor Bean，
	 * 如果实现了 Ordered 或使用了 @Order 注解，则按指定顺序执行。
	 * <p>该方法必须在所有单例 Bean 实例化之前调用，以确保配置类等逻辑生效。
	 */
	protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		// Delegate to PostProcessorRegistrationDelegate to invoke all BeanFactoryPostProcessors,
		// including those explicitly added via getBeanFactoryPostProcessors() and those defined as beans.
		// 委托给 PostProcessorRegistrationDelegate 处理所有 BeanFactoryPostProcessor，
		// 包括手动注册的和容器中通过注解等方式注册的。
		PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

		// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
		// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
		// 检查在执行过程中是否通过配置类动态注册了 LoadTimeWeaver Bean，
		// 如果存在，则为其注册一个处理器并设置临时类加载器，用于支持类加载时的织入（如 AspectJ）。
		if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}
	}

	/**
	 * Instantiate and register all BeanPostProcessor beans,
	 * respecting explicit order if given.
	 * <p>Must be called before any instantiation of application beans.
	 *
	 * 实例化并注册所有的 BeanPostProcessor 类型的 bean（即后置处理器），
	 * 并按照明确指定的顺序（如果有）进行排序和注册。
	 *
	 * 该方法必须在应用 Bean（普通 Bean）实例化之前调用，
	 * 否则 BeanPostProcessor 无法对那些普通 Bean 起作用。
	 */
	protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		// 委托给 PostProcessorRegistrationDelegate 执行真正的注册逻辑，
		// 并传入当前上下文作为 ApplicationContext。
		PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
	}

	/**
	 * 初始化当前应用上下文的 {@link MessageSource}。
	 * 优先使用上下文的配置
	 *
	 * Initialize the MessageSource.
	 * Use parent's if none defined in this context.
	 */
	protected void initMessageSource() {
		// 获取bean工厂，一般是DefaultListableBeanFactory
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		// 首先判断是否已有xml文件定义了id为messageSource的bean对象
		if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
			// 如果有，则从BeanFactory中获取这个对象
			this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
			// Make MessageSource aware of parent MessageSource.
			// 当父类bean工厂不为空，并且这个bean对象是HierarchicalMessageSource类型
			if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
				// 类型强制转换，转换为HierarchicalMessageSource的类型
				HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
				// 判断父类的messageSource是否为空，如果等于空，则设置父类的messageSource
				if (hms.getParentMessageSource() == null) {
					// Only set parent context as parent MessageSource if no parent MessageSource
					// registered already.
					hms.setParentMessageSource(getInternalParentMessageSource());
				}
			}
			if (logger.isTraceEnabled()) {
				logger.trace("Using MessageSource [" + this.messageSource + "]");
			}
		}
		else {
			// Use empty MessageSource to be able to accept getMessage calls.
			// 如果没有xml文件定义信息源对象，新建DelegatingMessageSource类作为messageSource的bean
			DelegatingMessageSource dms = new DelegatingMessageSource();
			// 给这个DelegatingMessageSource添加父类消息源
			dms.setParentMessageSource(getInternalParentMessageSource());
			this.messageSource = dms;
			// 将这个messageSource实例注册到bean工厂中
			beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
			if (logger.isTraceEnabled()) {
				logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
			}
		}
	}

	/**
	 * Initialize the ApplicationEventMulticaster.
	 * Uses SimpleApplicationEventMulticaster if none defined in the context.
	 *
	 * 初始化 ApplicationEventMulticaster（事件广播器）。
	 * 如果上下文中未定义自定义的广播器 Bean，则默认使用 SimpleApplicationEventMulticaster。
	 *
	 * <p>在 Spring 的监听器设计模式中，主要涉及以下 4 个核心角色：</p>
	 * <ul>
	 *   <li><b>事件（ApplicationEvent）</b>：
	 *       事件是对“发生了什么事情”的封装对象，例如容器刷新事件（ContextRefreshedEvent）、
	 *       容器关闭事件（ContextClosedEvent），也可以是用户自定义事件（如 UserRegisterEvent）。</li>
	 *
	 *   <li><b>监听器（ApplicationListener）</b>：
	 *       监听器会实现 ApplicationListener 接口，当事件发生时，
	 *       容器会调用监听器的 onApplicationEvent(E event) 方法进行响应处理。</li>
	 *
	 *   <li><b>事件多播器（ApplicationEventMulticaster）</b>：
	 *       广播器负责将事件分发给所有符合条件的监听器。
	 *       Spring 默认提供 SimpleApplicationEventMulticaster，它会将事件同步广播给所有监听器。
	 *       用户也可以自定义广播器（如异步分发）。</li>
	 *
	 *   <li><b>事件源（ApplicationContext）</b>：
	 *       Spring 容器本身就是事件源。调用 publishEvent() 方法即可发布事件，
	 *       容器会将事件交给广播器，再由广播器分发给监听器。</li>
	 * </ul>
	 *
	 * <p>调用链路总结：</p>
	 * <pre>
	 * ApplicationContext (事件源) ── publishEvent() ──▶ ApplicationEventMulticaster (事件多播器)
	 *        ── 分发 ──▶ ApplicationListener (监听器) ──▶ onApplicationEvent() 执行处理逻辑
	 * </pre>
	 *
	 * @see org.springframework.context.ApplicationEvent
	 * @see org.springframework.context.ApplicationListener
	 * @see org.springframework.context.event.ApplicationEventMulticaster
	 * @see org.springframework.context.event.SimpleApplicationEventMulticaster
	 */
	protected void initApplicationEventMulticaster() {
		// 获取当前容器的 BeanFactory
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();

		// 如果上下文中定义了名为 "applicationEventMulticaster" 的 Bean（用户自定义）
		if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
			// 获取并赋值给 applicationEventMulticaster
			this.applicationEventMulticaster =
					beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
			if (logger.isTraceEnabled()) {
				logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
			}
		}
		else {
			// 没有定义则使用默认的 SimpleApplicationEventMulticaster
			this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
			// 将其注册为单例 Bean，Bean 名称为 "applicationEventMulticaster"
			beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
			if (logger.isTraceEnabled()) {
				logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
						"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
			}
		}
	}

	/**
	 * Initialize the LifecycleProcessor.
	 * Uses DefaultLifecycleProcessor if none defined in the context.
	 * @see org.springframework.context.support.DefaultLifecycleProcessor
	 */
	protected void initLifecycleProcessor() {
		ConfigurableListableBeanFactory beanFactory = getBeanFactory();
		if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
			this.lifecycleProcessor =
					beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
			if (logger.isTraceEnabled()) {
				logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
			}
		}
		else {
			DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
			defaultProcessor.setBeanFactory(beanFactory);
			this.lifecycleProcessor = defaultProcessor;
			beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
			if (logger.isTraceEnabled()) {
				logger.trace("No '" + LIFECYCLE_PROCESSOR_BEAN_NAME + "' bean, using " +
						"[" + this.lifecycleProcessor.getClass().getSimpleName() + "]");
			}
		}
	}

	/**
	 * Template method which can be overridden to add context-specific refresh work.
	 * Called on initialization of special beans, before instantiation of singletons.
	 *
	 * 模板方法：允许子类在刷新容器时插入特定的扩展逻辑。
	 * 调用时机：在某些特殊 Bean 初始化完成后、普通单例 Bean 实例化之前被调用。
	 * 子类可以重写此方法以添加与上下文相关的刷新操作。
	 *
	 * <p>This implementation is empty.
	 * 该方法在父类中默认不做任何处理，留给子类去扩展。
	 *
	 * @throws BeansException in case of errors
	 * @see #refresh()
	 */
	protected void onRefresh() throws BeansException {
		// For subclasses: do nothing by default.
		// 默认空实现，供子类在必要时扩展，如 Web 应用环境下启动 DispatcherServlet。
	}

	/**
	 * Add beans that implement ApplicationListener as listeners.
	 * Doesn't affect other listeners, which can be added without being beans.
	 *
	 * 注册所有实现了 ApplicationListener 接口的监听器 Bean。
	 * 注意：此处只处理通过 Bean 方式定义的监听器，不影响以编程方式添加的监听器。
	 */
	protected void registerListeners() {
		// Register statically specified listeners first.
		// 1. 先注册通过代码显式添加的监听器（非 Bean），这些是通过 context.addApplicationListener() 添加的
		for (ApplicationListener<?> listener : getApplicationListeners()) {
			getApplicationEventMulticaster().addApplicationListener(listener);
		}

		// Do not initialize FactoryBeans here: We need to leave all regular beans
		// uninitialized to let post-processors apply to them!
		// 注意此处不能提前初始化 FactoryBean 或普通 Bean，要等后续处理器生效后再初始化。
		// 2. 获取容器中所有实现 ApplicationListener 接口的 Bean 名称（注意：延迟初始化）
		String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
		for (String listenerBeanName : listenerBeanNames) {
			// 将这些监听器的 Bean 名称注册到事件广播器，延迟到事件发生时再实例化
			getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
		}

		// Publish early application events now that we finally have a multicaster...
		// 3. 发布早期事件：在上下文刷新的早期阶段触发的事件（比如 early ContextRefreshedEvent）
		// 在广播器初始化完成之后再真正分发这些事件
		Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
		this.earlyApplicationEvents = null; // 清空早期事件缓存
		if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
			for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
				getApplicationEventMulticaster().multicastEvent(earlyEvent); // 分发早期事件
			}
		}
	}

	/**
	 * Finish the initialization of this context's bean factory,
	 * initializing all remaining singleton beans.
	 *
	 * 完成 BeanFactory 的初始化工作：
	 * - 初始化类型转换服务（ConversionService），支持属性值自动转换
	 * - 注册内嵌字符串值解析器，用于解析注解中的占位符（如 @Value）
	 * - 提前实例化 LoadTimeWeaverAware 类型的 bean（用于类加载器编织器）
	 * - 冻结 Bean 定义，防止后续修改
	 * - 实例化所有非懒加载的单例 bean
	 */
	protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
		// Initialize conversion service for this context.
		// 初始化类型转换服务（ConversionService），用于将属性值如 String 转换为 int、Date 等目标类型
		if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
				beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
			beanFactory.setConversionService(
					beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
		}

		// Register a default embedded value resolver if no BeanFactoryPostProcessor
		// (such as a PropertySourcesPlaceholderConfigurer bean) registered any before:
		// at this point, primarily for resolution in annotation attribute values.
		// 注册默认的内嵌值解析器（EmbeddedValueResolver），用于解析 @Value("${...}") 占位符
		if (!beanFactory.hasEmbeddedValueResolver()) {
			beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
		}

		// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
		// 提前初始化 LoadTimeWeaverAware 类型的 bean，用于运行时字节码增强
		String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
		for (String weaverAwareName : weaverAwareNames) {
			getBean(weaverAwareName);
		}

		// Stop using the temporary ClassLoader for type matching.
		// 不再使用临时类加载器（通常用于类型匹配）
		beanFactory.setTempClassLoader(null);

		// Allow for caching all bean definition metadata, not expecting further changes.
		// 冻结某些 Bean 定义，不再进行修改，标志着配置阶段结束，进入创建阶段
		beanFactory.freezeConfiguration();

		// Instantiate all remaining (non-lazy-init) singletons.
		// 实例化所有非懒加载的单例 bean
		beanFactory.preInstantiateSingletons();
	}

	/**
	 * 完成刷新
	 * Finish the refresh of this context, invoking the LifecycleProcessor's
	 * onRefresh() method and publishing the
	 * {@link org.springframework.context.event.ContextRefreshedEvent}.
	 */
	protected void finishRefresh() {
		// Clear context-level resource caches (such as ASM metadata from scanning).
		// 清除上下文级别的资源缓存(如扫描的ASM元数据)
		// 清空在资源加载器中的所有资源缓存
		clearResourceCaches();

		// Initialize lifecycle processor for this context.
		// 为这个上下文初始化生命周期处理器
		// 初始化LifecycleProcessor.如果上下文中找到'lifecycleProcessor'的LifecycleProcessor Bean对象，
		// 则使用DefaultLifecycleProcessor
		initLifecycleProcessor();

		// Propagate refresh to lifecycle processor first.
		// 首先将刷新传播到生命周期处理器
		// 上下文刷新的通知，例如自动启动的组件
		getLifecycleProcessor().onRefresh();

		// Publish the final event.
		// 发布最终事件
		// 新建ContextRefreshedEvent事件对象，将其发布到所有监听器。
		publishEvent(new ContextRefreshedEvent(this));

		// Participate in LiveBeansView MBean, if active.
		// 参与LiveBeansView MBean，如果是活动的
		// LiveBeansView:Sping用于支持JMX 服务的类
		// 注册当前上下文到LiveBeansView，以支持JMX服务
		LiveBeansView.registerApplicationContext(this);
	}

	/**
	 * Cancel this context's refresh attempt, resetting the {@code active} flag
	 * after an exception got thrown.
	 * @param ex the exception that led to the cancellation
	 */
	protected void cancelRefresh(BeansException ex) {
		this.active.set(false);
	}

	/**
	 * Reset Spring's common reflection metadata caches, in particular the
	 * {@link ReflectionUtils}, {@link AnnotationUtils}, {@link ResolvableType}
	 * and {@link CachedIntrospectionResults} caches.
	 * @since 4.2
	 * @see ReflectionUtils#clearCache()
	 * @see AnnotationUtils#clearCache()
	 * @see ResolvableType#clearCache()
	 * @see CachedIntrospectionResults#clearClassLoader(ClassLoader)
	 */
	protected void resetCommonCaches() {
		ReflectionUtils.clearCache();
		AnnotationUtils.clearCache();
		ResolvableType.clearCache();
		CachedIntrospectionResults.clearClassLoader(getClassLoader());
	}


	/**
	 * Register a shutdown hook {@linkplain Thread#getName() named}
	 * {@code SpringContextShutdownHook} with the JVM runtime, closing this
	 * context on JVM shutdown unless it has already been closed at that time.
	 * <p>Delegates to {@code doClose()} for the actual closing procedure.
	 * @see Runtime#addShutdownHook
	 * @see ConfigurableApplicationContext#SHUTDOWN_HOOK_THREAD_NAME
	 * @see #close()
	 * @see #doClose()
	 */
	@Override
	public void registerShutdownHook() {
		if (this.shutdownHook == null) {
			// No shutdown hook registered yet.
			this.shutdownHook = new Thread(SHUTDOWN_HOOK_THREAD_NAME) {
				@Override
				public void run() {
					synchronized (startupShutdownMonitor) {
						doClose();
					}
				}
			};
			Runtime.getRuntime().addShutdownHook(this.shutdownHook);
		}
	}

	/**
	 * Callback for destruction of this instance, originally attached
	 * to a {@code DisposableBean} implementation (not anymore in 5.0).
	 * <p>The {@link #close()} method is the native way to shut down
	 * an ApplicationContext, which this method simply delegates to.
	 * @deprecated as of Spring Framework 5.0, in favor of {@link #close()}
	 */
	@Deprecated
	public void destroy() {
		close();
	}

	/**
	 * Close this application context, destroying all beans in its bean factory.
	 * <p>Delegates to {@code doClose()} for the actual closing procedure.
	 * Also removes a JVM shutdown hook, if registered, as it's not needed anymore.
	 * @see #doClose()
	 * @see #registerShutdownHook()
	 */
	@Override
	public void close() {
		synchronized (this.startupShutdownMonitor) {
			doClose();
			// If we registered a JVM shutdown hook, we don't need it anymore now:
			// We've already explicitly closed the context.
			if (this.shutdownHook != null) {
				try {
					Runtime.getRuntime().removeShutdownHook(this.shutdownHook);
				}
				catch (IllegalStateException ex) {
					// ignore - VM is already shutting down
				}
			}
		}
	}

	/**
	 * Actually performs context closing: publishes a ContextClosedEvent and
	 * destroys the singletons in the bean factory of this application context.
	 * <p>Called by both {@code close()} and a JVM shutdown hook, if any.
	 * @see org.springframework.context.event.ContextClosedEvent
	 * @see #destroyBeans()
	 * @see #close()
	 * @see #registerShutdownHook()
	 */
	protected void doClose() {
		// Check whether an actual close attempt is necessary...
		if (this.active.get() && this.closed.compareAndSet(false, true)) {
			if (logger.isDebugEnabled()) {
				logger.debug("Closing " + this);
			}

			LiveBeansView.unregisterApplicationContext(this);

			try {
				// Publish shutdown event.
				publishEvent(new ContextClosedEvent(this));
			}
			catch (Throwable ex) {
				logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
			}

			// Stop all Lifecycle beans, to avoid delays during individual destruction.
			if (this.lifecycleProcessor != null) {
				try {
					this.lifecycleProcessor.onClose();
				}
				catch (Throwable ex) {
					logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
				}
			}

			// Destroy all cached singletons in the context's BeanFactory.
			destroyBeans();

			// Close the state of this context itself.
			closeBeanFactory();

			// Let subclasses do some final clean-up if they wish...
			onClose();

			// Reset local application listeners to pre-refresh state.
			if (this.earlyApplicationListeners != null) {
				this.applicationListeners.clear();
				this.applicationListeners.addAll(this.earlyApplicationListeners);
			}

			// Switch to inactive.
			this.active.set(false);
		}
	}

	/**
	 * Template method for destroying all beans that this context manages.
	 * The default implementation destroy all cached singletons in this context,
	 * invoking {@code DisposableBean.destroy()} and/or the specified
	 * "destroy-method".
	 * <p>Can be overridden to add context-specific bean destruction steps
	 * right before or right after standard singleton destruction,
	 * while the context's BeanFactory is still active.
	 * @see #getBeanFactory()
	 * @see org.springframework.beans.factory.config.ConfigurableBeanFactory#destroySingletons()
	 */
	protected void destroyBeans() {
		getBeanFactory().destroySingletons();
	}

	/**
	 * Template method which can be overridden to add context-specific shutdown work.
	 * The default implementation is empty.
	 * <p>Called at the end of {@link #doClose}'s shutdown procedure, after
	 * this context's BeanFactory has been closed. If custom shutdown logic
	 * needs to execute while the BeanFactory is still active, override
	 * the {@link #destroyBeans()} method instead.
	 */
	protected void onClose() {
		// For subclasses: do nothing by default.
	}

	@Override
	public boolean isActive() {
		return this.active.get();
	}

	/**
	 * Assert that this context's BeanFactory is currently active,
	 * throwing an {@link IllegalStateException} if it isn't.
	 * <p>Invoked by all {@link BeanFactory} delegation methods that depend
	 * on an active context, i.e. in particular all bean accessor methods.
	 * <p>The default implementation checks the {@link #isActive() 'active'} status
	 * of this context overall. May be overridden for more specific checks, or for a
	 * no-op if {@link #getBeanFactory()} itself throws an exception in such a case.
	 */
	protected void assertBeanFactoryActive() {
		if (!this.active.get()) {
			if (this.closed.get()) {
				throw new IllegalStateException(getDisplayName() + " has been closed already");
			}
			else {
				throw new IllegalStateException(getDisplayName() + " has not been refreshed yet");
			}
		}
	}


	//---------------------------------------------------------------------
	// Implementation of BeanFactory interface
	//---------------------------------------------------------------------

	@Override
	public Object getBean(String name) throws BeansException {
		assertBeanFactoryActive();
		return getBeanFactory().getBean(name);
	}

	@Override
	public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
		assertBeanFactoryActive();
		return getBeanFactory().getBean(name, requiredType);
	}

	@Override
	public Object getBean(String name, Object... args) throws BeansException {
		assertBeanFactoryActive();
		return getBeanFactory().getBean(name, args);
	}

	@Override
	public <T> T getBean(Class<T> requiredType) throws BeansException {
		assertBeanFactoryActive();
		return getBeanFactory().getBean(requiredType);
	}

	@Override
	public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
		assertBeanFactoryActive();
		return getBeanFactory().getBean(requiredType, args);
	}

	@Override
	public <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType) {
		assertBeanFactoryActive();
		return getBeanFactory().getBeanProvider(requiredType);
	}

	@Override
	public <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType) {
		assertBeanFactoryActive();
		return getBeanFactory().getBeanProvider(requiredType);
	}

	@Override
	public boolean containsBean(String name) {
		return getBeanFactory().containsBean(name);
	}

	@Override
	public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
		assertBeanFactoryActive();
		return getBeanFactory().isSingleton(name);
	}

	@Override
	public boolean isPrototype(String name) throws NoSuchBeanDefinitionException {
		assertBeanFactoryActive();
		return getBeanFactory().isPrototype(name);
	}

	@Override
	public boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException {
		assertBeanFactoryActive();
		return getBeanFactory().isTypeMatch(name, typeToMatch);
	}

	@Override
	public boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException {
		assertBeanFactoryActive();
		return getBeanFactory().isTypeMatch(name, typeToMatch);
	}

	@Override
	@Nullable
	public Class<?> getType(String name) throws NoSuchBeanDefinitionException {
		assertBeanFactoryActive();
		return getBeanFactory().getType(name);
	}

	@Override
	@Nullable
	public Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException {
		assertBeanFactoryActive();
		return getBeanFactory().getType(name, allowFactoryBeanInit);
	}

	@Override
	public String[] getAliases(String name) {
		return getBeanFactory().getAliases(name);
	}


	//---------------------------------------------------------------------
	// Implementation of ListableBeanFactory interface
	//---------------------------------------------------------------------

	@Override
	public boolean containsBeanDefinition(String beanName) {
		return getBeanFactory().containsBeanDefinition(beanName);
	}

	@Override
	public int getBeanDefinitionCount() {
		return getBeanFactory().getBeanDefinitionCount();
	}

	@Override
	public String[] getBeanDefinitionNames() {
		return getBeanFactory().getBeanDefinitionNames();
	}

	@Override
	public String[] getBeanNamesForType(ResolvableType type) {
		assertBeanFactoryActive();
		return getBeanFactory().getBeanNamesForType(type);
	}

	@Override
	public String[] getBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
		assertBeanFactoryActive();
		return getBeanFactory().getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
	}

	@Override
	public String[] getBeanNamesForType(@Nullable Class<?> type) {
		assertBeanFactoryActive();
		return getBeanFactory().getBeanNamesForType(type);
	}

	@Override
	public String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
		assertBeanFactoryActive();
		return getBeanFactory().getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
	}

	@Override
	public <T> Map<String, T> getBeansOfType(@Nullable Class<T> type) throws BeansException {
		assertBeanFactoryActive();
		return getBeanFactory().getBeansOfType(type);
	}

	@Override
	public <T> Map<String, T> getBeansOfType(@Nullable Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
			throws BeansException {

		assertBeanFactoryActive();
		return getBeanFactory().getBeansOfType(type, includeNonSingletons, allowEagerInit);
	}

	@Override
	public String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType) {
		assertBeanFactoryActive();
		return getBeanFactory().getBeanNamesForAnnotation(annotationType);
	}

	@Override
	public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType)
			throws BeansException {

		assertBeanFactoryActive();
		return getBeanFactory().getBeansWithAnnotation(annotationType);
	}

	@Override
	@Nullable
	public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
			throws NoSuchBeanDefinitionException {

		assertBeanFactoryActive();
		return getBeanFactory().findAnnotationOnBean(beanName, annotationType);
	}


	//---------------------------------------------------------------------
	// Implementation of HierarchicalBeanFactory interface
	//---------------------------------------------------------------------

	@Override
	@Nullable
	public BeanFactory getParentBeanFactory() {
		return getParent();
	}

	@Override
	public boolean containsLocalBean(String name) {
		return getBeanFactory().containsLocalBean(name);
	}

	/**
	 * Return the internal bean factory of the parent context if it implements
	 * ConfigurableApplicationContext; else, return the parent context itself.
	 *
	 * <p>如果父上下文实现了 ConfigurableApplicationContext 接口，
	 * 则返回其内部的 BeanFactory；否则直接返回父上下文本身。
	 * <p>通常用于在多层应用上下文中访问父容器的 BeanFactory，
	 * 以便进行 Bean 的获取或定义查找。
	 *
	 * @see org.springframework.context.ConfigurableApplicationContext#getBeanFactory
	 */
	@Nullable
	protected BeanFactory getInternalParentBeanFactory() {
		// 如果父上下文是 ConfigurableApplicationContext，则取其内部 BeanFactory
		// 否则直接返回父上下文对象（它本身也是 BeanFactory）
		return (getParent() instanceof ConfigurableApplicationContext ?
				((ConfigurableApplicationContext) getParent()).getBeanFactory() : getParent());
	}


	//---------------------------------------------------------------------
	// Implementation of MessageSource interface
	//---------------------------------------------------------------------

	@Override
	public String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale) {
		return getMessageSource().getMessage(code, args, defaultMessage, locale);
	}

	@Override
	public String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException {
		return getMessageSource().getMessage(code, args, locale);
	}

	@Override
	public String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException {
		return getMessageSource().getMessage(resolvable, locale);
	}

	/**
	 * Return the internal MessageSource used by the context.
	 * @return the internal MessageSource (never {@code null})
	 * @throws IllegalStateException if the context has not been initialized yet
	 */
	private MessageSource getMessageSource() throws IllegalStateException {
		if (this.messageSource == null) {
			throw new IllegalStateException("MessageSource not initialized - " +
					"call 'refresh' before accessing messages via the context: " + this);
		}
		return this.messageSource;
	}

	/**
	 * Return the internal message source of the parent context if it is an
	 * AbstractApplicationContext too; else, return the parent context itself.
	 */
	@Nullable
	protected MessageSource getInternalParentMessageSource() {
		return (getParent() instanceof AbstractApplicationContext ?
				((AbstractApplicationContext) getParent()).messageSource : getParent());
	}


	//---------------------------------------------------------------------
	// Implementation of ResourcePatternResolver interface
	//---------------------------------------------------------------------

	@Override
	public Resource[] getResources(String locationPattern) throws IOException {
		return this.resourcePatternResolver.getResources(locationPattern);
	}


	//---------------------------------------------------------------------
	// Implementation of Lifecycle interface
	//---------------------------------------------------------------------

	@Override
	public void start() {
		getLifecycleProcessor().start();
		publishEvent(new ContextStartedEvent(this));
	}

	@Override
	public void stop() {
		getLifecycleProcessor().stop();
		publishEvent(new ContextStoppedEvent(this));
	}

	@Override
	public boolean isRunning() {
		return (this.lifecycleProcessor != null && this.lifecycleProcessor.isRunning());
	}


	//---------------------------------------------------------------------
	// Abstract methods that must be implemented by subclasses
	//---------------------------------------------------------------------

	/**
	 * Subclasses must implement this method to perform the actual configuration load.
	 * The method is invoked by {@link #refresh()} before any other initialization work.
	 * <p>A subclass will either create a new bean factory and hold a reference to it,
	 * or return a single BeanFactory instance that it holds. In the latter case, it will
	 * usually throw an IllegalStateException if refreshing the context more than once.
	 * @throws BeansException if initialization of the bean factory failed
	 * @throws IllegalStateException if already initialized and multiple refresh
	 * attempts are not supported
	 */
	protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;

	/**
	 * Subclasses must implement this method to release their internal bean factory.
	 * This method gets invoked by {@link #close()} after all other shutdown work.
	 * <p>Should never throw an exception but rather log shutdown failures.
	 */
	protected abstract void closeBeanFactory();

	/**
	 * Subclasses must return their internal bean factory here. They should implement the
	 * lookup efficiently, so that it can be called repeatedly without a performance penalty.
	 * <p>Note: Subclasses should check whether the context is still active before
	 * returning the internal bean factory. The internal factory should generally be
	 * considered unavailable once the context has been closed.
	 * @return this application context's internal bean factory (never {@code null})
	 * @throws IllegalStateException if the context does not hold an internal bean factory yet
	 * (usually if {@link #refresh()} has never been called) or if the context has been
	 * closed already
	 * @see #refreshBeanFactory()
	 * @see #closeBeanFactory()
	 */
	@Override
	public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;


	/**
	 * Return information about this context.
	 */
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder(getDisplayName());
		sb.append(", started on ").append(new Date(getStartupDate()));
		ApplicationContext parent = getParent();
		if (parent != null) {
			sb.append(", parent: ").append(parent.getDisplayName());
		}
		return sb.toString();
	}

}
